﻿namespace A2DFramework.OSGI.Processors
{
    using A2DFramework.OSGI;
    using A2DFramework.OSGI.BundleContexts;
    using A2DFramework.OSGI.Configuration;
    using A2DFramework.OSGI.Helps;
    using System;
    using System.Runtime.CompilerServices;

    public class ModuleSandBox : MarshalByRefObject, IModuleSandBox, IDisposable
    {
        private IBundleActivator activator;
        private AppDomain appDomain;
        private BundleContext context;
        private ModuleInfo moduleInfo;

        public ModuleSandBox(ModuleInfo moduleInfo)
        {
            this.moduleInfo = moduleInfo;
            this.ModuleName = this.moduleInfo.Name;
            AppDomainSetup info = new AppDomainSetup {
                ApplicationBase = moduleInfo.ModuleRootPath,
                ApplicationName = moduleInfo.Name
            };
            this.appDomain = AppDomain.CreateDomain(moduleInfo.Name, null, info);
            this.appDomain.SetData("RuntimeAppDomain", AppDomain.CurrentDomain);
        }

        public object CreateInstance(string type)
        {
            return this.appDomain.CreateInstanceAndUnwrap(this.moduleInfo.Assembly, type);
        }

        public void Dispose()
        {
            Console.WriteLine("SandBox [" + this.moduleInfo.Name + "] Dispose");
        }

        public void Init()
        {
            Console.WriteLine("SandBox [" + this.moduleInfo.Name + "] Init");
            this.context = new RuntimeContext(this.moduleInfo.Name);
            this.activator = (IBundleActivator) this.CreateInstance(this.moduleInfo.Activator);
        }

        public void RegisterOSGIService(string requestServiceType, string serviceProviderType, int prot, string serviceUri)
        {
            AppDomainDelegate delegate2 = new AppDomainDelegate(requestServiceType, serviceProviderType, prot, serviceUri);
            this.appDomain.DoCallBack(new CrossAppDomainDelegate(delegate2.RegisterOSGIService));
        }

        public void Start()
        {
            this.activator.Startup(this.context);
            foreach (string str in this.moduleInfo.ProvidedServices)
            {
                if (!this.context.IsRegisteredService(str))
                {
                    throw new Exception("Not found service for: " + str);
                }
            }
        }

        public void Stop()
        {
            this.activator.Stop(this.context);
        }

        public string ModuleName { get; private set; }

        [Serializable]
        private class AppDomainDelegate
        {
            private int prot;
            private string requestServiceType;
            private string serviceProviderType;
            private string serviceUri;

            public AppDomainDelegate(string requestServiceType, string serviceProviderType, int prot, string serviceUri)
            {
                this.requestServiceType = requestServiceType;
                this.serviceProviderType = serviceProviderType;
                this.prot = prot;
                this.serviceUri = serviceUri;
            }

            public void RegisterOSGIService()
            {
                RemotingServiceHelper.RegisterOSGIService(this.requestServiceType, this.serviceProviderType, this.prot, this.serviceUri);
            }
        }
    }
}

